AI项目实战(6)代码审查 Agent

《AI Agent 实战》系列 · 代码审查 Agent

Posted by Ryan on 2026-06-28
Estimated Reading Time 23 Minutes
Words 5.6k In Total
Viewed Times

老王是公司里的资深工程师,工位上常年摆着三块屏幕。每天早上一打开代码托管平台,二十几个 PR 排着队等他 review。他不是不乐意审,是真审不动——光是把每个 PR 的改动看完就要大半天,更别提还要查规范、追漏洞、跑测试。结果呢?常常审到第 15 个 PR 时眼皮打架,一个 SQL 注入就这么从眼皮底下溜了过去,上线第二天数据库就被拖走了。

新人的处境也没好到哪去。小李刚入职,兴冲冲提了第一个 PR,挂在那儿三天没人看。等到终于有人路过点了两下,留下一句"看着没问题"就 approve 了。一周后线上告警,回过头一查,问题就藏在那段没人认真看过的代码里。

这两端的痛,指向同一件事:代码审查这件事,光靠人盯,是盯不住的。 于是有了本章的主角——代码审查 Agent。我们要让 Agent 像老王一样审代码:会读文件、会搜模式、会从安全/性能/规范三个维度挑刺,还会跑测试验证。区别只有一点:Agent 不会打瞌睡,也不嫌 PR 多。

全书主线进度:第 4 章的 RAG Agent 让 Agent 学会了查资料,但它干活还是"一问一答"——你说一句,它用一次工具,回一句。真实任务可比这复杂多了。代码审查就是典型:要"读文件 → 搜模式 → 安全审查 → 性能审查 → 规范审查 → 建议修复 → 跑测试验证"。这是多轮、多维度、还得自我修正的活儿。本章攻克两个关键能力:Harness 循环(让 Agent 反复地想-做-看-再想)和 Skill 封装(把审查方法论打包成可复用模块)。

主讲能力:Harness 循环 + Skill 技能封装
业务场景:自动审查代码变更,检查安全漏洞、性能问题、编码规范,输出结构化审查报告。
技术栈:LangChain v1.0 create_agent + 三个审查 Skill + 文件读写/搜索/测试工具


5.1 老王的心愿

5.1.1 业务背景与痛点

把老王和小李的遭遇拆开看,代码审查的痛其实就四条:

  • 初级工程师的代码,缺一个经验老到的审查者把关;
  • 安全漏洞(SQL 注入、XSS)藏在 PR 里,人眼一晃就过;
  • 同一类规范问题被反复指出,审的人烦、改的人也烦;
  • 修完没人自动验证,按下葫芦浮起瓢,引入新问题。

人工审查的覆盖面有限,效率还会随团队扩大直线下降。既然如此,能不能把"老王式的审查"固化下来,让 Agent 不知疲倦地干?这就是本项目要回答的问题。

5.1.2 用户故事

把上面的痛翻译成一张用户故事表,需求就清晰了:

编号 作为 我想要 以便
US-1 开发者 PR 提交后立刻得到自动化审查报告 修复问题后再找同事审查
US-2 架构师 审查覆盖安全、性能、规范三个维度 不会漏掉关键问题
US-3 Tech Lead 审查报告结构化(JSON),便于接入 CI 在 CI 中自动拦截高危问题
US-4 开发者 审查后可选地自动运行测试 确认修复不引入回归

5.1.3 功能性需求

  • FR-1 文件读取:Agent 能读取待审查的文件内容
  • FR-2 代码搜索:Agent 能用 grep 搜索潜在问题模式(如硬编码密钥)
  • FR-3 三维度审查:安全、性能、规范逐维度进行
  • FR-4 结构化报告:JSON 格式,含文件路径、行号、严重程度、修复建议
  • FR-5 测试执行:可选地运行 pytest 验证

5.2 画个样子:它该长啥样

用户提交一个代码文件,Agent 就该像老王接过 PR 一样开工:先读文件、再搜模式,然后分别掏出三本"审查手册"——安全、性能、规范——逐条对照,最后汇成一份结构化报告。要是不放心,还能顺手跑一遍测试。整条流水线画出来是这样的:

%%{init: {'theme':'base','flowchart':{'useMaxWidth':true,'htmlLabels':true}}}%%
graph TD
    U["用户提交代码文件"] --> Agent["代码审查 Agent"]
    Agent --> R["read_file 读取文件"]
    Agent --> G["grep_code 搜索模式"]
    R & G --> S1["🛡️ Security Skill
SQL注入/XSS/密钥泄露"] R & G --> S2["⚡ Performance Skill
N+1查询/复杂度"] R & G --> S3["📐 Style Skill
命名/类型/长度"] S1 & S2 & S3 --> Report["结构化报告
JSON: issues[], score"] Agent --> Test["run_tests
(可选)验证修复"] classDef uN fill:#e3f2fd,stroke:#1976d2,stroke-width:2px,color:#0d47a1 classDef aN fill:#ede7f6,stroke:#5e35b1,stroke-width:2px,color:#311b92 classDef tN fill:#e0f7fa,stroke:#00acc1,stroke-width:2px,color:#006064 classDef sN fill:#e0f2f1,stroke:#00897b,stroke-width:2px,color:#004d40 class U uN class Agent aN class R,G,Test tN class S1,S2,S3,Report sN

5.3 拆开看:怎么造出来

5.3.1 技术选型

技术点 选型 理由
Agent create_agent 内置 agent loop(自动多轮)
工具 read_file / grep_code / run_tests 对应的就是真实代码审查工具
Skill ReviewSkill 基类 + 3 个子类 每个审查维度独立封装,可插拔
模型 Claude Sonnet 4.6 强代码理解能力

5.3.2 关键设计:Skill 模块化——把老王的经验写成 SOP 手册

老王审了十年代码,脑子里攒了一堆"经验法则":看到 password = 就要警惕硬编码、看到循环里有数据库查询就要查 N+1、看到函数超过 50 行就想让人拆……这些经验平时只活在老王脑子里,新人学不到,老王一休假就断了档。

Skill 做的事,就是把这些经验一条条抠出来,写成一本"审查 SOP 手册"。每翻开一页(一个 Skill),Agent 就瞬间变成那个维度的专家。不同于项目一直接把 Prompt 写死在代码里,本章把"审查方法论"抽象为 ReviewSkill 类:每个 Skill 有自己的 nameprompt_template,要增加新的审查维度(比如"国际化审查"),只需新增一个子类,已有代码一行都不用动。

💡 顿悟时刻:Skill 的本质,是"把人的隐性经验,变成 Agent 的显性能力"。新人一翻手册就变专家,老王休假也不怕——因为经验已经长在代码里了。

5.3.3 关键设计:Harness 循环——像老王那样"看一眼、查一下、再回头看"

很多人第一次接触 Agent 都会冒出一个问题:现在的大模型那么强,把整个文件丢给它,让它一次审完不行吗?为什么要绕着圈循环?

我当初也是这么想的。直到我真把一个 500 行的文件丢给模型,让它"全面审查"。它确实吐了一份报告,但读下来你会发现:满纸都是"建议增加注释""变量名可更清晰"这类不痛不痒的话,而那个藏在第 317 行的 SQL 拼接,它压根没提。

为什么?因为"一次性审完"违背了人脑审查的方式。回头看看老王是怎么审一个 PR 的:

  1. 先扫一眼 diff——“这段在拼 SQL?嗯,可疑。”
  2. 翻出公司的安全规范,对照一下——“确认了,拼接 SQL 是高危。”
  3. 还不放心,grep 一下整个仓库——“看看还有没有别的地方也这么写。”
  4. 跑一下相关测试——“看会不会挂。”
  5. 回头再看一眼最初那段代码——这时候的判断,已经比第一眼深了好几层。

老王从来不是一眼扫完就写报告,他是带着疑问一步步往下挖的。看到第 50 行的 SQL 拼接,他会停下来专门去搜;搜完回来,对第 50 行的判断就变了。审查的质量,来自"看了之后回头再想"的来回,而不是一次性看完。

create_agent 内置的 agent loop,正是逼着模型像人一样,一步、一停、一回头:

  1. 读文件 → 发现潜在问题
  2. 用 grep 搜索确认 → 定位到具体行
  3. 对照 Skill 的审查标准 → 形成报告
  4. 如果有修复建议 → 用户可以要求重新审查(开启新一轮循环)

每跑一圈,模型对这份代码的理解就深一层。这就是 Harness 循环存在的理由,也是它反直觉却必不可少的地方。

💡 金句:一次性审完,得到的是"走马观花";循环着审,得到的才是"老王的眼光"。


5.4 动手写:三层架构完整代码

5.4.1 架构分层总览

层级 文件名 职责 核心类/函数
领域模型层 models.py 定义审查相关的数据结构、状态枚举、Skill 基类 ReviewIssue, ReviewReport, ReviewSkill, Severity
提示词层 prompts.py 集中管理所有系统提示词和审查模板 build_system_prompt(), build_dimension_review_prompt()
工具层 tools.py 封装文件读取、代码搜索、测试运行等工具 read_file, grep_code, run_tests
服务层 service.py 业务逻辑编排、静态规则检查、缓存管理 CodeReviewService
项目入口层 project.py Agent 构建、项目注册、API 适配 CodeReviewProject
导出层 __init__.py 对外导出、向后兼容 所有 public API

5.4.2 models.py - 领域模型层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
"""P03 代码审查 Agent - 领域模型层"""
from __future__ import annotations

import json
from dataclasses import asdict, dataclass, field
from datetime import datetime
from enum import Enum
from typing import Any


class Severity(str, Enum):
"""问题严重程度枚举。"""
HIGH = "高危"
MEDIUM = "中危"
LOW = "低危"


class ReviewDimension(str, Enum):
"""审查维度枚举。"""
SECURITY = "security"
PERFORMANCE = "performance"
STYLE = "style"


@dataclass
class ReviewIssue:
"""单个审查问题条目。"""
file_path: str
line_number: int | None = None
severity: Severity = Severity.LOW
dimension: ReviewDimension = ReviewDimension.STYLE
description: str = ""
suggestion: str = ""
code_snippet: str = ""

def validate(self) -> list[str]:
"""验证字段合法性,返回错误列表。"""
errors: list[str] = []
if not self.file_path:
errors.append("file_path 不能为空")
if not self.description:
errors.append("description 不能为空")
return errors

def to_dict(self) -> dict[str, Any]:
data = asdict(self)
data["severity"] = self.severity.value
data["dimension"] = self.dimension.value
return data


@dataclass
class ReviewReport:
"""完整的审查报告。"""
target_files: list[str] = field(default_factory=list)
issues: list[ReviewIssue] = field(default_factory=list)
score: int = 10
reviewed_at: str = field(default_factory=lambda: datetime.now().isoformat())
duration_seconds: float = 0.0

@property
def issue_count(self) -> dict[str, int]:
counts: dict[str, int] = {"高危": 0, "中危": 0, "低危": 0}
for issue in self.issues:
counts[issue.severity.value] += 1
return counts

def calculate_score(self) -> int:
base = 10
for issue in self.issues:
if issue.severity == Severity.HIGH:
base -= 2
elif issue.severity == Severity.MEDIUM:
base -= 1
return max(1, min(10, int(round(base))))


class ReviewSkill:
"""审查 Skill 基类。"""
name: str = ""
dimension: ReviewDimension = ReviewDimension.STYLE
prompt_template: str = ""


class SecurityReviewSkill(ReviewSkill):
"""安全审查 Skill。"""
name = "security"
dimension = ReviewDimension.SECURITY
prompt_template = """你是安全审计专家。审查以下代码的安全问题:
- SQL 注入(拼接 SQL 字符串)
- XSS 漏洞(直接输出用户输入未转义)
- 硬编码的密钥/密码/Token
- 命令注入(os.system / subprocess 拼接用户输入)
对每个发现的问题标注严重程度,并提供可直接执行的修复代码。"""


class PerformanceReviewSkill(ReviewSkill):
"""性能审查 Skill。"""
name = "performance"
dimension = ReviewDimension.PERFORMANCE
prompt_template = """你是性能优化专家。审查以下代码的性能问题:
- N+1 查询(循环内执行数据库查询)
- 不必要的 O(n) 操作(可用 O(1) 替代)
- 大对象未释放(内存泄漏风险)
- 可并行化的串行操作"""


class StyleReviewSkill(ReviewSkill):
"""编码规范审查 Skill。"""
name = "style"
dimension = ReviewDimension.STYLE
prompt_template = """你是代码规范专家。审查以下代码的规范问题:
- 函数/变量命名是否符合 PEP 8(snake_case)
- 缺少类型注解(函数参数和返回值)
- 函数过长(超过 50 行建议拆分)
- 缺少 docstring(模块、类、公共方法)
- 过深的嵌套层级(超过 3 层)"""


REVIEW_SKILLS: list[ReviewSkill] = [
SecurityReviewSkill(),
PerformanceReviewSkill(),
StyleReviewSkill(),
]

核心代码讲解

  • 枚举类型安全SeverityReviewDimensionstr 枚举,既保证了类型安全,又能直接序列化进 JSON——老王写报告可不想再手动转换一遍"高危"两个字
  • 数据验证ReviewIssue.validate() 给每条问题兜底,确保最终报告里不会出现"光有行号没有描述"这种半拉子条目
  • 可扩展的 Skill 设计:想加新审查维度?继承 ReviewSkill、填一段 prompt_template 就完事——这正是前文说的"往 SOP 手册里再塞一页"

5.4.3 prompts.py - 提示词层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
"""P03 代码审查 Agent - Prompt 层"""
from __future__ import annotations

from .models import REVIEW_SKILLS, ReviewSkill

AGENT_SYSTEM_PROMPT = """你是高级代码审查 Agent,负责对代码变更进行全面审查。

## 核心职责
1. 读取待审查的文件内容
2. 从安全、性能、规范三个维度逐一审查
3. 输出结构化的审查报告(JSON 格式)

## 输出格式要求
必须输出 JSON 格式的审查报告,结构如下:
```json
{{
"target_files": ["path/to/file.py"],
"issues": [
{{
"file_path": "path/to/file.py",
"line_number": 42,
"severity": "高危",
"dimension": "security",
"description": "问题描述",
"suggestion": "修复建议"
}}
],
"score": 8
}}

审查维度

{review_dimensions}
“”"

def build_system_prompt() -> str:
“”“构建完整的系统提示词,动态注入审查维度。”“”
dimensions_desc = []
for skill in REVIEW_SKILLS:
first_line = skill.prompt_template.split(‘\n’)[0]
dimensions_desc.append(f"- {skill.name.upper()}: {first_line}“)
return AGENT_SYSTEM_PROMPT.format(review_dimensions=”\n".join(dimensions_desc))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

**核心代码讲解**:
- **集中管理**:所有提示词收在一个文件里,就像把老王的口头规矩统一抄到一本手册上,便于维护和版本控制
- **动态构建**:`build_system_prompt()` 自动遍历已注册的 Skill,挨个拼出维度说明——新增 Skill 时,提示词会自动跟上,不用手动改
- **格式契约**:白纸黑字写死了 JSON 输出结构,确保下游解析时不会因为格式漂移而炸场

---

### 5.4.4 tools.py - 工具层

```python
"""P03 代码审查 Agent - 工具层"""
from __future__ import annotations

import subprocess
from pathlib import Path

from langchain.tools import tool

from core.logging_conf import get_logger

logger = get_logger("p03.code_review.tools")
MAX_FILE_SIZE = 8000


@tool
def read_file(file_path: str) -> str:
"""读取指定文件的全部内容。"""
logger.info("读取文件: %s", file_path)
try:
path = Path(file_path)
if not path.exists():
return f"文件不存在: {file_path}"
content = path.read_text(encoding="utf-8")
if len(content) > MAX_FILE_SIZE:
content = content[:MAX_FILE_SIZE] + f"\n... (已截断至 {MAX_FILE_SIZE} 字符)"
return content
except Exception as e:
logger.exception("读取文件失败: %s", e)
return f"读取文件失败: {type(e).__name__}: {e}"


@tool
def grep_code(pattern: str, directory: str = ".") -> str:
"""在指定目录中搜索代码模式(正则表达式)。"""
logger.info("代码搜索: pattern='%s'", pattern)
try:
result = subprocess.run(
["grep", "-rn", "--include=*.py", "-n", pattern, directory],
capture_output=True,
text=True,
timeout=10,
)
if not result.stdout.strip():
return f"未找到匹配 '{pattern}' 的代码"
return result.stdout
except Exception as e:
logger.exception("搜索失败: %s", e)
return f"搜索失败: {type(e).__name__}: {e}"


@tool
def run_tests(repo_path: str = ".") -> str:
"""在指定目录运行 Python 测试套件。"""
logger.info("运行测试: repo_path=%s", repo_path)
try:
result = subprocess.run(
["python", "-m", "pytest", "-x", "--tb=short", "-q"],
capture_output=True,
text=True,
timeout=60,
cwd=repo_path,
)
return result.stdout or result.stderr
except Exception as e:
logger.exception("测试运行失败: %s", e)
return f"测试运行失败: {type(e).__name__}: {e}"

核心代码讲解

  • 错误降级:每个工具都裹了 try/except,失败时返回一句友好的人话,而不是让整个 Agent 崩掉——就像老王审到读不了的文件会跳过继续,而不是摔键盘走人
  • 资源保护read_file 设了 8000 字截断,防止大文件撑爆上下文窗口;子进程都挂了 timeout,免得一条 grep 把 Agent 卡死到天黑
  • 可观测性:每次工具调用都打日志,事后能复盘 Agent 这一圈到底干了啥

⚠️ 避坑:当前 read_file 只检查了"文件存不存在",并没有限制路径范围。要是有人传进 ../../../../etc/passwd 这类路径,Agent 会乖乖读出来。生产环境记得补上 Path.resolve() 加根目录校验,把 Agent 关在自己的项目院子里,别放它出去乱翻。


5.4.5 service.py - 服务层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
"""P03 代码审查 Agent - 服务层"""
from __future__ import annotations

import time

from core.logging_conf import get_logger

from .models import REVIEW_SKILLS, ReviewIssue, ReviewReport, Severity

logger = get_logger("p03.code_review.service")


class CodeReviewService:
"""代码审查服务。"""

def __init__(self, skills=None):
self.skills = skills or REVIEW_SKILLS
logger.info("代码审查服务初始化完成,加载 %d 个审查 Skill", len(self.skills))

def review_file(self, file_path: str, run_grep: bool = True) -> ReviewReport:
"""审查单个文件。"""
start_time = time.time()
logger.info("开始审查文件: %s", file_path)

report = ReviewReport(target_files=[file_path])

# 静态规则检查
static_issues = self._static_rule_check(file_path)
report.issues.extend(static_issues)

report.score = report.calculate_score()
report.duration_seconds = time.time() - start_time
return report

def _static_rule_check(self, file_path: str, content: str) -> list[ReviewIssue]:
"""静态规则检查(简单的字符串模式匹配)。"""
issues: list[ReviewIssue] = []
lines = content.split("\n")

for line_no, line in enumerate(lines, 1):
if "password" in line.lower() and "=" in line and "os.getenv" not in line:
issues.append(ReviewIssue(
file_path=file_path,
line_number=line_no,
severity=Severity.HIGH,
description="可能存在硬编码密码",
suggestion="使用 os.getenv('PASSWORD') 从环境变量读取",
code_snippet=line.strip(),
))
return issues

核心代码讲解

  • 职责分层清晰:Service 层并不直接去调 LLM,而是干那些"不需要脑子"的活儿——静态规则匹配、报告聚合。LLM 该干的循环审查交给 Agent,两边各司其职
  • 可观测性:完整的执行时间统计加日志记录,审查慢了能一眼看出卡在哪
  • 可配置:Skill 列表能从外面注入,换一套 Skill 跑测试、做扩展都方便

5.4.6 project.py - 项目入口层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
"""P03 代码审查 Agent - 项目入口层"""
from __future__ import annotations

from langchain.agents import create_agent

from core import BaseProject, build_chat_model, registry
from core.logging_conf import get_logger

from .prompts import build_system_prompt
from .tools import get_available_tools

logger = get_logger("p03.code_review.project")


class CodeReviewProject(BaseProject):
"""代码审查 Agent 项目。"""

id = "p03_code_review"
name = "代码审查 Agent"
description = "自动审查代码安全、性能、规范,输出结构化报告。"
capabilities = ["Harness", "Skill", "代码审查"]

def build_agent(self) -> any:
"""构建代码审查 Agent。"""
logger.info("正在构建代码审查 Agent...")
model = build_chat_model()
tools = get_available_tools()
system_prompt = build_system_prompt()
return create_agent(model=model, tools=tools, system_prompt=system_prompt)


registry.register(CodeReviewProject())

核心代码讲解

  • 统一接口:继承 BaseProject,与全书所有项目保持一致的对外 API——换个项目也不用重新学一套用法
  • 装配线模式build_agent() 就是一条装配线,依次备好模型、工具、提示词,最后用 create_agent 拧成一台完整的审查机器
  • 自动注册:导入即注册到全局注册表,调度时一喊就到

5.4.7 init.py - 导出层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
"""项目三:代码审查 Agent(生产级 Harness + Skill)"""
from __future__ import annotations

# 领域模型
from .models import (
REVIEW_SKILLS,
PerformanceReviewSkill,
ReviewIssue,
ReviewReport,
ReviewSkill,
SecurityReviewSkill,
Severity,
StyleReviewSkill,
)

# 提示词
from .prompts import build_system_prompt

# 工具
from .tools import grep_code, read_file, run_tests

# 服务
from .service import CodeReviewService

# 项目入口
from .project import CodeReviewProject

# 向后兼容
SYSTEM_PROMPT = build_system_prompt()

__all__ = [
"Severity", "ReviewIssue", "ReviewReport", "ReviewSkill",
"SecurityReviewSkill", "PerformanceReviewSkill", "StyleReviewSkill",
"REVIEW_SKILLS", "build_system_prompt", "SYSTEM_PROMPT",
"read_file", "grep_code", "run_tests",
"CodeReviewService", "CodeReviewProject",
]

核心代码讲解

  • 明确的导出边界__all__ 把对外导出的符号列得明明白白,哪些能用、哪些是内部细节,一目了然
  • 向后兼容SYSTEM_PROMPT 这个别名留着一截旧代码的命,旧代码不用改也能继续跑
  • 模块化导入:用户能按需取用——只想要工具写个脚本也行,想要整个 Project 跑全套也行

5.5 跑一跑:它真的行吗

光说不练假把式。下面这几条测试,把工具和 Skill 的关键行为都盯死了:

测试 验证内容
test_read_file 文件读取工具正常工作
test_read_file_not_found 文件不存在时返回友好提示
test_grep_code 代码搜索工具正常工作
test_skills_loaded 三个 Skill 全部加载,名称正确
test_review_simple_file(集成) Agent 能识别硬编码密码和 SQL 注入

最后那条集成测试是重头戏:真把一段藏着硬编码密码和 SQL 注入的代码喂给 Agent,看它能不能像老王一样把这两条揪出来。


5.6 送上线:让它上班

同第 2 章——继承 BaseProject,自动接入统一 API。不用额外操心发布的事。


5.7 回头看:学到了什么

回头看,这一章 Agent 学会的两样本事,都藏在老王身上:

能力 在本项目中的体现
Harness 循环 create_agent 内置 agent loop,读→搜→审→报告,多轮不间断
Skill 封装 ReviewSkill 基类 + 三个子类,新增审查维度只需加一个新子类
工具集成 read_file / grep_code / run_tests — 对应真实审查工作流

常见坑

  1. 审查 Prompt 太泛——一句"请审查这个代码"换来的报告,往往又水又没重点。按 Skill 维度把 Prompt 拆开,质量立刻提上来。老王审 PR 也不是一句"看看"完事,他是分门别类地挑。
  2. 文件太大——read_file 做了 8000 字截断,过大的文件得拆开来分块审,硬塞只会让 Agent"看花眼"。
  3. 只跑了一个 Skill——要是只审了安全、漏了性能和规范,报告就不完整。三个维度都得过一遍,才算真审完。

📌 项目三完成。 Agent 学会了"多轮反复审查"和"把经验打包成 Skill"。下一章我们将攻克 MCP——标准化的工具接入协议——让 Agent 能连上数据库、API、任意外部系统。


如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !